<?php
namespace slinks\extensions\aop\core;

/**
 * Provides dynamic proxying support for any target. 
 * @author navid
 *
 */
class AutoProxy{
	
	private $target;
	
	private $interceptors;
	
	private $className;
	
	/**
	 * Creates a new AutoProxy
	 * @param object $target any object that will have its methods intercepted. 
	 * @param array $interceptors of interceptor objects that want to intercept the given target.
	 */
	function __construct($target,array $interceptors = array()){
		$this->target = & $target;
		$this->interceptors = $interceptors;
		$this->className = get_class($this->target);
	}
	
	public function __call($method, $arguments) {
		
		// call the interceptors
		/* @var $interceptor IInterceptor */
		foreach ($this->interceptors as $interceptor){
			$interceptor->before($this->className, $method, $arguments);
		}
		
		$ret = null;
	    if (method_exists($this->target, $method)) {
	    	try{
            	$ret = call_user_func_array(array($this->target, $method), $arguments);
	    	}catch(\Exception $e){
	    		$errorOccured = true;
	    		foreach ($this->interceptors as $interceptor){
					$interceptor->exception($this->className, $method, $arguments, $e);
	    		}
	    		throw $e;
			}
        }else{
        	throw new \BadMethodCallException('Method '.$method.' not implemented for '.$this->className.'.');
        }
        

		foreach ($this->interceptors as $interceptor){
			$interceptor->after($this->className, $method, $arguments, $ret);
		}
        
        return $ret;
	}
	
	
}


